package org.fireflow2.designer.eclipse.commands.workflownode;

import java.util.List;
import java.util.UUID;

import org.fireflow.model.ModelElement;
import org.fireflow.pdl.fpdl20.diagram.EndNodeShape;
import org.fireflow.pdl.fpdl20.diagram.Fpdl20DiagramElement;
import org.fireflow.pdl.fpdl20.diagram.StartNodeShape;
import org.fireflow.pdl.fpdl20.diagram.basic.Bounds;
import org.fireflow.pdl.fpdl20.diagram.basic.Label;
import org.fireflow.pdl.fpdl20.diagram.basic.impl.BoundsImpl;
import org.fireflow.pdl.fpdl20.diagram.basic.impl.CircleImpl;
import org.fireflow.pdl.fpdl20.diagram.basic.impl.LabelImpl;
import org.fireflow.pdl.fpdl20.diagram.basic.impl.PointImpl;
import org.fireflow.pdl.fpdl20.diagram.impl.EndNodeShapeImpl;
import org.fireflow.pdl.fpdl20.diagram.impl.RouterShapeImpl;
import org.fireflow.pdl.fpdl20.diagram.impl.StartNodeShapeImpl;
import org.fireflow.pdl.fpdl20.process.EndNode;
import org.fireflow.pdl.fpdl20.process.Router;
import org.fireflow.pdl.fpdl20.process.StartNode;
import org.fireflow.pdl.fpdl20.process.SubProcess;
import org.fireflow.pdl.fpdl20.process.features.endnode.ThrowCompensationFeature;
import org.fireflow.pdl.fpdl20.process.features.endnode.ThrowFaultFeature;
import org.fireflow.pdl.fpdl20.process.features.endnode.ThrowTerminationFeature;
import org.fireflow.pdl.fpdl20.process.features.endnode.impl.ThrowCompensationFeatureImpl;
import org.fireflow.pdl.fpdl20.process.features.endnode.impl.ThrowFaultFeatureImpl;
import org.fireflow.pdl.fpdl20.process.features.endnode.impl.ThrowTerminationFeatureImpl;
import org.fireflow.pdl.fpdl20.process.features.router.impl.AndJoinAndSplitRouterFeature;
import org.fireflow.pdl.fpdl20.process.features.router.impl.CustomizedRouterFeature;
import org.fireflow.pdl.fpdl20.process.features.router.impl.DynamicRouterFeature;
import org.fireflow.pdl.fpdl20.process.features.router.impl.OrJoinOrSplitRouterFeature;
import org.fireflow.pdl.fpdl20.process.features.startnode.CatchCompensationFeature;
import org.fireflow.pdl.fpdl20.process.features.startnode.CatchFaultFeature;
import org.fireflow.pdl.fpdl20.process.features.startnode.TimerStartFeature;
import org.fireflow.pdl.fpdl20.process.features.startnode.WebserviceStartFeature;
import org.fireflow.pdl.fpdl20.process.features.startnode.impl.CatchCompensationFeatureImpl;
import org.fireflow.pdl.fpdl20.process.features.startnode.impl.CatchFaultFeatureImpl;
import org.fireflow.pdl.fpdl20.process.features.startnode.impl.TimerStartFeatureImpl;
import org.fireflow.pdl.fpdl20.process.features.startnode.impl.WebserviceStartFeatureImpl;
import org.fireflow.pdl.fpdl20.process.impl.EndNodeImpl;
import org.fireflow.pdl.fpdl20.process.impl.RouterImpl;
import org.fireflow.pdl.fpdl20.process.impl.StartNodeImpl;
import org.fireflow2.designer.eclipse.commands.AbstractCreateNodeCommand;
import org.fireflow2.designer.eclipse.modelwrapper.NodeWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.SubProcessWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.basic.EndNodeWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.basic.RouterWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.basic.StartNodeWrapper;
import org.fireflow2.designer.eclipse.palette.DiagramElementSubType;

public class CreateWorkflowNodeCommand extends AbstractCreateNodeCommand {

	protected NodeWrapper createNodeWrapper(){
		SubProcessWrapper subflowWrapper = null;
		if (this.parentWrapper instanceof SubProcessWrapper){
			subflowWrapper = (SubProcessWrapper)this.parentWrapper;
		}else{
			subflowWrapper = ((NodeWrapper)this.parentWrapper).getSubProcessWrapper();
		}
		NodeWrapper tmpNodeWrapper = null;
		SubProcess subflow = (SubProcess)subflowWrapper.getWorkflowModelElement();		
		if (diagramElm == Fpdl20DiagramElement.END_NODE){
			String name = findANewNodeName(subflow,"EndNode");
			EndNode endNode = new EndNodeImpl((SubProcess)subflowWrapper.getWorkflowModelElement(),name);
			if (this.subType==null || subType.equals(DiagramElementSubType.EMPTY)){
				//不用设置feature
			}else if (this.subType.equals(DiagramElementSubType.END_TERMINATION)){
				ThrowTerminationFeature f = new ThrowTerminationFeatureImpl();
				endNode.setFeature(f);
			}
			else if (this.subType.equals(DiagramElementSubType.END_THROW_FAULT_END)){
				ThrowFaultFeature f = new ThrowFaultFeatureImpl();
				endNode.setFeature(f);
				
			}else if (this.subType.equals(DiagramElementSubType.END_THROW_COMPENSATION_END)){
				ThrowCompensationFeature f = new ThrowCompensationFeatureImpl();
				endNode.setFeature(f);
			}

			String shapeId = UUID.randomUUID().toString();
			EndNodeShape endNodeShape = new EndNodeShapeImpl(shapeId);
			endNodeShape.setWorkflowElementRef(endNode.getId());
			
			CircleImpl circle = new CircleImpl();
			Label lb = new LabelImpl();
			lb.getFont().setSize(10);
			circle.setLabel(lb);
			
			PointImpl theCenter = null;
			if (rect.width>0){
				theCenter = new PointImpl(rect.x+rect.width/2,rect.y+rect.height/2);
			}else{
				theCenter = new PointImpl(rect.x,rect.y);
			}
			circle.setTheCenter(theCenter);
			int radius = 16;
			circle.setRadius(radius);
			endNodeShape.setShape(circle);
			
			tmpNodeWrapper = new EndNodeWrapper(subflowWrapper,(EndNode)endNode,endNodeShape);
		}
		else if (diagramElm  == Fpdl20DiagramElement.START_NODE){
			String name = findANewNodeName(subflow,"StartNode");
			StartNode startNode = new StartNodeImpl((SubProcess)subflowWrapper.getWorkflowModelElement(),name);
			if (this.subType==null || subType.equals(DiagramElementSubType.EMPTY)){
				//不用设置feature
			}else if (this.subType.equals(DiagramElementSubType.START_TIMER_START)){
				TimerStartFeature f = new TimerStartFeatureImpl();
				startNode.setFeature(f);
			}
			else if (this.subType.equals(DiagramElementSubType.START_WS_START)){
				WebserviceStartFeature f = new WebserviceStartFeatureImpl();
				startNode.setFeature(f);
				
			}else if (this.subType.equals(DiagramElementSubType.START_CATCH_FAULT_START)){
				CatchFaultFeature f = new CatchFaultFeatureImpl();
				startNode.setFeature(f);
			}
			else if (this.subType.equals(DiagramElementSubType.START_CATCH_COMPENSATION_START)){
				CatchCompensationFeature f = new CatchCompensationFeatureImpl();
				startNode.setFeature(f);
			}
			
			String shapeId = UUID.randomUUID().toString();
			StartNodeShape startNodeShape = new StartNodeShapeImpl(shapeId);
			startNodeShape.setWorkflowElementRef(startNode.getId());
			
			CircleImpl circle = new CircleImpl();
			Label lb = new LabelImpl();
			lb.getFont().setSize(10);
			circle.setLabel(lb);
			
			PointImpl theCenter = new PointImpl();
			if (rect!=null){
				if (rect.width>0){
					theCenter = new PointImpl(rect.x+rect.width/2,rect.y+rect.height/2);
				}else{
					theCenter = new PointImpl(rect.x,rect.y);
				}
			}

			circle.setTheCenter(theCenter);
			int radius = 16;
			/*
			//注释掉，采用固定大小的StartNode
			if (rect.width>0 && rect.height>0){
				radius = rect.width>rect.height?rect.height/2:rect.width/2;
			}
			*/
			circle.setRadius(radius);
			startNodeShape.setShape(circle);

			tmpNodeWrapper = new StartNodeWrapper(subflowWrapper,(StartNode)startNode,startNodeShape);
		}		
		else if (diagramElm  == Fpdl20DiagramElement.ROUTER){
			String name = findANewNodeName(subflow,"Router");
			Router router = new RouterImpl((SubProcess)subflowWrapper.getWorkflowModelElement(),name);
			if (this.subType==null || subType.equals(DiagramElementSubType.EMPTY)){
				//不用设置feature
			}else if (this.subType.equals(DiagramElementSubType.ROUTER_INCLUSIVE)){
				DynamicRouterFeature f = new DynamicRouterFeature();
				router.setFeature(f);
			}else if (this.subType.equals(DiagramElementSubType.ROUTER_PARALLEL)){
				AndJoinAndSplitRouterFeature f = new AndJoinAndSplitRouterFeature();
				router.setFeature(f);
			}else if (this.subType.equals(DiagramElementSubType.ROUTER_EXCLUSIVE)){
				OrJoinOrSplitRouterFeature f = new OrJoinOrSplitRouterFeature();
				router.setFeature(f);
			}else if (this.subType.equals(DiagramElementSubType.ROUTER_COMPLEX)){
				CustomizedRouterFeature f = new CustomizedRouterFeature();
				router.setFeature(f);
			}

			String shapeId = UUID.randomUUID().toString();
			RouterShapeImpl startRouterShape = new RouterShapeImpl(shapeId);
			startRouterShape.setWorkflowElementRef(router.getId());
			
			org.fireflow.pdl.fpdl20.diagram.basic.Rectangle theRectangle = new org.fireflow.pdl.fpdl20.diagram.basic.impl.RectangleImpl();
			PointImpl theCenter = null;
			if (rect.width>0){
				theCenter = new PointImpl(rect.x+rect.width/2,rect.y+rect.height/2);
			}else{
				theCenter = new PointImpl(rect.x,rect.y);
			}
			Bounds bound = new BoundsImpl();
			bound.setUpperLeftCorner(new PointImpl(theCenter.getX()-16,theCenter.getY()-16));
			bound.setHeight(32);
			bound.setWidth(32);
			bound.setBoundsStyle(null);

			theRectangle.setBounds(bound);
			theRectangle.setFulfilStyle(null);
			theRectangle.getTitleLabel().getFont().setSize(10);
			theRectangle.setContentLabel(null);//Router 不需要content
			startRouterShape.setShape(theRectangle);
			
			
			tmpNodeWrapper = new RouterWrapper(subflowWrapper,router,startRouterShape);
		}
		return tmpNodeWrapper;
	}
	
	protected String findANewNodeName(SubProcess subprocess,String nodeType){
		boolean exist = true;
		int n = 1;
		List nodes = null;
		if (nodeType.equals("StartNode")){
			nodes = subprocess.getStartNodes();
		}
		else if (nodeType.equals("Activity")){
			nodes = subprocess.getActivities();
		}else if (nodeType.equals("Router")){
			nodes = subprocess.getRouters();
		}else if (nodeType.equals("EndNode")){
			nodes = subprocess.getEndNodes();
		}
		
		String name = nodeType
			+ (nodes.size() + n);	
		if (nodes==null || nodes.size()==0){
			return name;
		}		
		while(exist){
			boolean found = false;
			for (int i=0;i<nodes.size();i++){
				ModelElement node = (ModelElement)nodes.get(i);
				if (name.equals(node.getName())){
					n++;
					name = nodeType
						+ (nodes.size() + n);
					found = true;
					break;
				}
			}
			if (!found){
				exist=false;
			}
		}
		return name;
	}		
}
